package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
)

// 这个是文件读和写
func main1() {
	fileInfo, err := os.Stat("./demo.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(fileInfo.Name())
	fmt.Println("w文件", fileInfo)
	// 大小
	fmt.Println(fileInfo.Size())
	//是否是文件夹
	fmt.Println(fileInfo.IsDir())
	//判断是否是绝对路径
	filepath.IsAbs("./dome.txt")
	//获取绝对路径
	fmt.Println(filepath.Abs("./demo.txt"))
	//创建文件夹
	// err = os.Mkdir("./var", os.ModePerm) // os.modeperm 等同与0777   //另外mkdirall 是创建层级目录
	// if err != nil {
	// 	fmt.Println(err)
	// 	return
	// }
	//创建文件 create  权限为0666(任何人可读写,不可执行)
	file1, _ := os.Create("./bb.txt")
	fmt.Println("这个是文件的指针或者为文件的地址:", file1)
	//打开文件  使用open为只读打开
	file1, err = os.Open("./demo.txt")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("f输出打开后的文件地址,", &file1)
	file1.Close()
	//下面为读写打开
	file1, err = os.OpenFile("./bb1.txt", os.O_RDWR|os.O_CREATE, 0777) // 三个参数, 文件路径 打开方式 不存在是赋予创建权限
	if err != nil {
		fmt.Println("读写打开报错:", err)
		return
	}
	file1.Close()
	//删除文件及文件夹
	err = os.Remove("./bb1.txt")
	//删除层级文件及文件夹
	err = os.RemoveAll("./var")
	fmt.Println("文件删除成功")
	fmt.Println("文件操作,全部完成")
}

// 这个是文件的复制, 写入和读取 这个未优化,如果字节数量很多, 会导致文件复制只能复制一部分
func main3() {

	//打开文件
	file, err := os.Open("./img.jpg")
	if err != nil {
		fmt.Println("打开文件报错", err)
		return
	}
	// 读取数据
	bs := make([]byte, 1024, 8024)
	n, err1 := file.Read(bs)
	if err1 != nil {
		fmt.Println("读取字节报错", err1)
		return
	}
	defer file.Close()

	// fmt.Println("读取到的数据为:", string(bs[:n]))  //验证后,后续需要隐藏
	// 写入数据
	file, err = os.OpenFile("./copyimg.jpg", os.O_CREATE, os.ModePerm) //注意文件后缀
	if err != nil {
		fmt.Println("创建文件报错", err)
		return
	}
	defer file.Close()

	n, err = file.Write(bs[:n]) //把读取内容写入的bs中, 写入数量为读取的数量n
	if err != nil {
		fmt.Println("写入数据报错", err)
	}
	fmt.Println("程序执行完毕")
}

// 创建两个变量以及一个函数, 用来封装读取和写入操作
func main2() {

	//打开文件
	file, err := os.Open("./copyimg.jpg")
	if err != nil {
		fmt.Println("打开文件报错", err)
		return
	}
	defer file.Close()
	// 读取数据
	bs := make([]byte, 8024, 8024)
	n, err1 := file.Read(bs)
	if err1 != nil {
		fmt.Println("读取字节报错", err1)
		return
	}
	fmt.Println("读取到的数据为:", string(bs[:n])) //验证后,后续需要隐藏
}

// 这个是main3 优化后的方法, 优化后解决: 字节一次无法读取和写入完全的问题
func main4() {

	//打开文件
	file, err := os.Open("./img.jpg")
	if err != nil {
		fmt.Println("打开文件报错", err)
		// return  这里不能用return
	}

	file1, err := os.OpenFile("./copyimg.jpg", os.O_CREATE, os.ModePerm) //注意文件后缀
	if err != nil {
		fmt.Println("创建文件报错", err)
		return
	}
	defer file.Close()
	defer file1.Close()
	// 循环读取数据,并限制条件写入
	// var total int = 0
	bs := make([]byte, 1024, 1024)
	var num int = 0
	for {
		n, err1 := file.Read(bs)
		if err != nil {
			fmt.Println("读取数据报错", err)
			// return
		}
		if err1 == io.EOF || n == 0 {
			num += n
			fmt.Printf("数据完全写入成功,本次写入字节数:%d,共计写入字节数:%d", n, num)
			return
		}
		n, err = file1.Write(bs[:n]) //写入内容
		if err != nil {
			fmt.Println("写入数据报错", err)
			return
		}
		fmt.Println("数据完全写入成功,写入字节数:", n)
		num += n
	}
	fmt.Println("程序执行完毕")
}

// 使用os.copy方法使其进行文件复制   这个方法最好用 使用 io.copy(写入文件对象,读取文件对象)
func main() {
	//直接定义两个文件
	filepath := "./img.jpg"
	filepath2 := "./copyimg.jpg"
	file, err := os.Open(filepath)
	if err != nil {
		fmt.Println("读取文件报错", err)
		return
	}
	file2, err := os.OpenFile(filepath2, os.O_CREATE, os.ModePerm)
	if err != nil {
		fmt.Println("创建并赋予文件权限错误")
		return
	}
	defer file.Close()
	defer file2.Close()
	//复制文件
	n, err := io.Copy(file2, file) // 注意被复制的文件在前
	if err != nil {
		fmt.Println("复制文件错误", err)
	}
	fmt.Println("复制字节数为:", n)
}

// 第三种 复制文件方法, 使用 iotuil方法 ioutil.Readfile 和 ioutilWritefile 两个方法   该方法以弃用
func mian5() {
	// file1, err := os.Open("./img.jpg")
	// file2, err := os.OpenFile("./copyimg.jpg", os.O_CREATE, 0777)
	// err = ioutil.ReadFile(file1)
	// err := ioutil.ReadFile("./img.jpg")

}
